﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DDD {
    /// <summary>
    /// リソース
    /// </summary>
    /// <remarks>
    /// リソースは弱い参照(<see cref="WeakReference"/>)の<see cref="Object"/>と
    /// 任意の値(<typeparamref name="TValue"/>のペアを保存します。
    /// 紐付けは弱い参照によって行われるのでここ以外の参照が全て消えると
    /// <see cref="Object"/>はGCによって削除・回収され不正な状態になります。
    /// この時<see cref="Object"/>はnullを返します。保存していたキーの型は<see cref="ObjectType"/>で取得してください。
    /// </remarks>
    /// <typeparam name="TValue">リソースとして保存する値の型</typeparam>
    public struct Cache<TValue> where TValue : struct {

        #region Field
        WeakReference obj;
        TValue value;
        Type objectType;
        #endregion

        /// <summary>
        /// コンストラクター
        /// </summary>
        /// <param name="key">紐付けする任意の<dic>Object</dic></param>
        /// <param name="value">紐付けする値</param>
        public Cache (Object key, TValue value) : this() {
            this.obj = new WeakReference (key);
            this.value = value;
            this.objectType = key.GetType ();
        }

        
        /// <summary>
        /// キーとなるオブジェクト.
        /// </summary>
        public Object Object { 
            get { return (Object)obj.Target;}
        }

        /// <summary>
        /// 保存されたバリュー.
        /// </summary>
        public TValue Value {
            get { return value; }
        }

        /// <summary>
        /// キーオブジェクトの型
        /// </summary>
        public Type ObjectType {
            get { return objectType; }
        }


        /// <summary>
        /// このリソースの有効無効フラグ
        /// </summary>
        /// <remarks>
        /// キーの<see cref="Object"/>がGCに回収されていなければtrue,
        /// 回収済みならfalseを返します。
        /// </remarks>
        public bool IsValid {
            get { return obj.IsAlive; }
        }

        /// <summary>
        /// 現在のオブジェクトの状態を表す文字列を返します。
        /// </summary>
        /// <returns>現在のオブジェクトを説明する文字列</returns>
        public override string ToString () {
            var name = (Object == null) ? "null" : Object.GetType ().Name;
            return string.Format("Resource: Key={0}, Value={1}", name, Value);
        }
    }
}
